package com.itlong.cloud.controller.property;

import com.itlong.cloud.POJO.DTO.BaseDTO;
import com.itlong.cloud.POJO.DTO.property.*;
import com.itlong.cloud.POJO.VO.MessageVO;
import com.itlong.cloud.POJO.VO.property.PropertyParkingGetVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.abstracts.BaseController;
import com.itlong.cloud.annotation.AuthAccessRequired;
import com.itlong.cloud.annotation.LoggerInfo;
import com.itlong.cloud.constants.LogDescConstant;
import com.itlong.cloud.enumerate.FileCatalogEnum;
import com.itlong.cloud.enumerate.ecode.BaseErrorCodeEnum;
import com.itlong.cloud.enumerate.ecode.ErrorCode;
import com.itlong.cloud.enumerate.ecode.PropertyErrorCodeEnum;
import com.itlong.cloud.project.property.IPropertyParkingServiceClient;
import com.itlong.cloud.thrown.DataAccessException;
import com.itlong.cloud.utils.file.UploadFileUtil;
import com.itlong.cloud.utils.network.http.HttpProtocolUtil;
import com.itlong.cloud.utils.page.Page;
import com.itlong.cloud.utils.words.NumberHandlerUtil;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.DataFormatter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * <desc>
 *      物业管理-车位管理控制器
 * </desc>
 *
 * @createDate 2018/08/17
 */
@RestController
@RequestMapping("/project/parking")
@RefreshScope
public class PropertyParkingController extends BaseController {

    @Value("${" + PlatformConstants.FILE_FTP_HOST + "}")
    public String FILE_FTP_HOST;

    @Value("${" + PlatformConstants.FILE_FTP_PORT + "}")
    public String FILE_FTP_PORT;

    @Value("${" + PlatformConstants.FILE_FTP_USERNAME + "}")
    public String FILE_FTP_USERNAME;

    @Value("${" + PlatformConstants.FILE_FTP_PASSWORD + "}")
    public String FILE_FTP_PASSWORD;

    @Value("${" + PlatformConstants.FILE_ACCESS_URL + "}")
    public String FILE_ACCESS_URL;

    @Autowired
    private IPropertyParkingServiceClient iPropertyParkingServiceClient;

    /**
     * <desc>
     *      添加车位信息
     * </desc>
     *
     * @param propertyParkingSaveDTO 添加车位信息数据DTO
     * @return 标准格式化响应结果
     * @author wangzhi
     * @createDate 2018/08/17
     */
    @ResponseBody
    @PostMapping(path = "saveParking")
    @AuthAccessRequired
    @LoggerInfo(operateDesc = LogDescConstant.PARKING_SAVE_LOG_DESC)
    public Object saveParking(PropertyParkingSaveDTO propertyParkingSaveDTO){
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            propertyParkingSaveDTO = HttpProtocolUtil.parseRequestParamToDTO(PropertyParkingSaveDTO.class, request);
            if (propertyParkingSaveDTO == null || StringUtils.isBlank(propertyParkingSaveDTO.getParkingNum()) || StringUtils.isBlank(propertyParkingSaveDTO.getParkingArea())) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            if (StringUtils.isBlank(propertyParkingSaveDTO.getProjectId())) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            if (propertyParkingSaveDTO.getParkingType() == null || StringUtils.isBlank(propertyParkingSaveDTO.getParkingType().toString())
                    || propertyParkingSaveDTO.getParkingStatus() == null || StringUtils.isBlank(propertyParkingSaveDTO.getParkingStatus().toString())) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            String regex = "^[^\u4e00-\u9fa5]{1,10}$";
            if (!Pattern.compile(regex).matcher(propertyParkingSaveDTO.getParkingNum()).matches()) {
                return new MessageVO(PropertyErrorCodeEnum.PARKING_NUM_CHINESE_ERR.getErrorCode());
            }
            PropertyParkingGetOneDTO propertyParkingGetOneDTO = new PropertyParkingGetOneDTO();
            propertyParkingGetOneDTO.setProjectId(propertyParkingSaveDTO.getProjectId());
            propertyParkingGetOneDTO.setParkingNum(propertyParkingSaveDTO.getParkingNum());
            PropertyParkingGetVO oneParking = iPropertyParkingServiceClient.getOneParking(propertyParkingGetOneDTO);
            if (oneParking != null) {
                return new MessageVO(PropertyErrorCodeEnum.PARKING_NUM_EXIST_ERR.getErrorCode());
            }
            iPropertyParkingServiceClient.saveParking(propertyParkingSaveDTO);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException("【物业-物业管理】添加车位信息失败",e);
        }
    }

    /**
     * <desc>
     *      分页列表查询车位信息
     * </desc>
     *
     * @param propertyParkingGetListDTO 列表查询车位信息数据DTO
     * @return 标准格式化响应结果
     * @author wangzhi
     * @createDate 2018/08/17
     */
    @ResponseBody
    @AuthAccessRequired
    @PostMapping(path = "getParkingsByPage")
    public Object getParkingsByPage(PropertyParkingGetListDTO propertyParkingGetListDTO){
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            propertyParkingGetListDTO = HttpProtocolUtil.parseRequestParamToDTO(PropertyParkingGetListDTO.class, request);
            if (propertyParkingGetListDTO == null) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            if (StringUtils.isBlank(propertyParkingGetListDTO.getProjectId())) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            Page<PropertyParkingGetVO> propertyParkingGetVOS = iPropertyParkingServiceClient.getParkingsByPage(propertyParkingGetListDTO);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),propertyParkingGetVOS);
        } catch (Exception e) {
            throw new DataAccessException("【物业-物业管理】列表查询车位信息失败",e);
        }
    }

    /**
     * <desc>
     *      获取单个车位信息
     * </desc>
     *
     * @param propertyParkingGetOneDTO 查询参数
     * @return 标准格式化响应结果
     * @author wangzhi
     * @createDate 2018/08/17
     */
    @ResponseBody
    @PostMapping(path = "getOneParking")
    public Object getOneParking(PropertyParkingGetOneDTO propertyParkingGetOneDTO){
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            propertyParkingGetOneDTO = HttpProtocolUtil.parseRequestParamToDTO(PropertyParkingGetOneDTO.class, request);
            if (propertyParkingGetOneDTO == null) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            if (StringUtils.isBlank(propertyParkingGetOneDTO.getProjectId())) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            if (StringUtils.isBlank(propertyParkingGetOneDTO.getParkingId()) && StringUtils.isBlank(propertyParkingGetOneDTO.getParkingNum())) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            PropertyParkingGetVO propertyParkingGetVO = iPropertyParkingServiceClient.getOneParking(propertyParkingGetOneDTO);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),propertyParkingGetVO);
        } catch (Exception e) {
            throw new DataAccessException("【物业-物业管理】获取单个车位信息失败",e);
        }
    }

    /**
     * <desc>
     *      修改车位信息
     * </desc>
     *
     * @param propertyParkingUpdateDTO 修改参数
     * @return 标准格式化响应结果
     * @author wangzhi
     * @createDate 2018/08/17
     */
    @ResponseBody
    @PostMapping("updateParking")
    @AuthAccessRequired
    @LoggerInfo(operateDesc = LogDescConstant.PARKING_UPDATE_LOG_DESC)
    public Object updateParking(PropertyParkingUpdateDTO propertyParkingUpdateDTO){
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            propertyParkingUpdateDTO = HttpProtocolUtil.parseRequestParamToDTO(PropertyParkingUpdateDTO.class, request);
            if (propertyParkingUpdateDTO == null || StringUtils.isBlank(propertyParkingUpdateDTO.getParkingNum()) || StringUtils.isBlank(propertyParkingUpdateDTO.getParkingArea())
                    || StringUtils.isBlank(propertyParkingUpdateDTO.getParkingId())) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            if (StringUtils.isBlank(propertyParkingUpdateDTO.getProjectId())) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            if (propertyParkingUpdateDTO.getParkingType() == null || StringUtils.isBlank(propertyParkingUpdateDTO.getParkingType().toString())
                    || propertyParkingUpdateDTO.getParkingStatus() == null || StringUtils.isBlank(propertyParkingUpdateDTO.getParkingStatus().toString())) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            String regex = "^[^\u4e00-\u9fa5]{1,10}$";
            if (!Pattern.compile(regex).matcher(propertyParkingUpdateDTO.getParkingNum()).matches()) {
                return new MessageVO(PropertyErrorCodeEnum.PARKING_NUM_CHINESE_ERR.getErrorCode());
            }
            PropertyParkingGetOneDTO propertyParkingGetOneDTO = new PropertyParkingGetOneDTO();
            propertyParkingGetOneDTO.setParkingNum(propertyParkingUpdateDTO.getParkingNum());
            propertyParkingGetOneDTO.setProjectId(propertyParkingUpdateDTO.getProjectId());
            PropertyParkingGetVO oneParking = iPropertyParkingServiceClient.getOneParking(propertyParkingGetOneDTO);
            if (oneParking != null && !propertyParkingUpdateDTO.getParkingId().equals(oneParking.getParkingId())) {
                return new MessageVO(PropertyErrorCodeEnum.PARKING_NUM_EXIST_ERR.getErrorCode());
            }
            iPropertyParkingServiceClient.updateParking(propertyParkingUpdateDTO);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException("【物业-物业管理】修改车位信息失败",e);
        }
    }

    /**
     * <desc>
     *      批量删除车位信息
     * </desc>
     *
     * @param parkingIds 车位id，多个用英文","相连
     * @return 标准格式化响应结果
     * @author wangzhi
     * @createDate 2018/08/17
     */
    @ResponseBody
    @PostMapping("deleteParkings")
    @AuthAccessRequired
    @LoggerInfo(operateDesc = LogDescConstant.PARKING_DELETE_LOG_DESC)
    public Object deleteParkings(String parkingIds){
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            parkingIds = request.getAttribute("parkingIds") == null ? null : request.getAttribute("parkingIds").toString();
            if (StringUtils.isBlank(parkingIds)) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            iPropertyParkingServiceClient.deleteParkings(parkingIds);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException("【物业-物业管理】批量删除车位信息失败",e);
        }
    }

    /**
     * <desc>
     *      下载表单导入模板
     * </desc>
     *
     * @return 标准格式化响应结果
     * @author wangzhi
     * @createDate 2018/08/17
     */
    @ResponseBody
    @AuthAccessRequired
    @PostMapping("getExcelTemplate")
    public Object getExcelTemplate(){
        try {
            String templateFilePath = FILE_ACCESS_URL + FileCatalogEnum.PROJECT_STATIC_FILE.getType()
                    + PlatformConstants.PARKING_IMPORT_TEMPLATE_FILE_NAME;
            URI excelTemplateDownLoadUrl = new URI(templateFilePath);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),(Object) excelTemplateDownLoadUrl.toString());
        } catch (Exception e) {
            throw new DataAccessException("【物业-物业管理】下载表单导入模板失败",e);
        }
    }

    /**
     * <desc>
     *      导出车位表单
     * </desc>
     *
     * @param propertyParkingGetListDTO 列表查询车位信息数据DTO
     * @return 标准格式化响应结果
     * @author wangzhi
     * @createDate 2018/08/17
     */
    @ResponseBody
    @AuthAccessRequired
    @PostMapping("exportParkings")
    public Object exportParkings(PropertyParkingGetListDTO propertyParkingGetListDTO){
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            propertyParkingGetListDTO = HttpProtocolUtil.parseRequestParamToDTO(PropertyParkingGetListDTO.class, request);
            if (propertyParkingGetListDTO == null) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            if (StringUtils.isBlank(propertyParkingGetListDTO.getProjectId())) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            List<PropertyParkingGetVO> propertyParkingGetVOS = iPropertyParkingServiceClient.getAllParkings(propertyParkingGetListDTO);
            if (propertyParkingGetVOS == null || propertyParkingGetVOS.isEmpty()) {
                return new MessageVO(PropertyErrorCodeEnum.EXPORT_DATA_EMPTY_ERR.getErrorCode());
            }
            if (propertyParkingGetVOS.size() > 2000) {
                return new MessageVO(PropertyErrorCodeEnum.EXPORT_DATA_TOO_MANY_ERR.getErrorCode());
            }
            String[] title = {"序号","车位号","车位面积(m²)","车位类型","车位状态","备注","创建时间"};
            short rowHeight= 420;
            //创建excel工作簿
            HSSFWorkbook workbook=new HSSFWorkbook();
            //创建工作表sheet并设置简单格式
            HSSFSheet sheet=workbook.createSheet();
            sheet.setDefaultColumnWidth(15);
            //创建第一行
            HSSFRow row=sheet.createRow(0);
            row.setHeight(rowHeight);
            HSSFCell cell=null;
            //插入第一行数据的表头
            for (int i = 0; i < title.length; i++) {
                cell = row.createCell(i);
                cell.setCellValue(title[i]);
            }
            //写入数据
            for (int parkingIndex = 0; parkingIndex < propertyParkingGetVOS.size(); parkingIndex++) {
                PropertyParkingGetVO propertyParkingGetVO = propertyParkingGetVOS.get(parkingIndex);
                int rowIndex = parkingIndex + 1; // 第一行已为标题行
                HSSFRow dataRow = sheet.createRow(rowIndex);
                dataRow.setHeight(rowHeight);
                HSSFCell noteCell = dataRow.createCell(0);
                noteCell.setCellValue(rowIndex);
                noteCell = dataRow.createCell(1);
                noteCell.setCellValue(propertyParkingGetVO.getParkingNum());
                noteCell = dataRow.createCell(2);
                noteCell.setCellValue(propertyParkingGetVO.getParkingArea());
                noteCell = dataRow.createCell(3);
                switch (propertyParkingGetVO.getParkingType()){
                    case 1:
                        noteCell.setCellValue("公共车位");
                        break;
                    case 2:
                        noteCell.setCellValue("人防车位");
                        break;
                    case 3:
                        noteCell.setCellValue("产权车位");
                        break;
                    default:
                        noteCell.setCellValue("无");
                        break;
                }
                noteCell = dataRow.createCell(4);
                switch (propertyParkingGetVO.getParkingStatus()){
                    case 1:
                        noteCell.setCellValue("临停");
                        break;
                    case 2:
                        noteCell.setCellValue("已售");
                        break;
                    case 3:
                        noteCell.setCellValue("已租");
                        break;
                    case 4:
                        noteCell.setCellValue("空置");
                        break;
                    case 5:
                        noteCell.setCellValue("自用");
                        break;
                    case 6:
                        noteCell.setCellValue("待售");
                        break;
                    case 7:
                        noteCell.setCellValue("待租");
                        break;
                    default:
                        noteCell.setCellValue("无");
                        break;
                }
                noteCell = dataRow.createCell(5);
                noteCell.setCellValue(propertyParkingGetVO.getRemark());
                noteCell = dataRow.createCell(6);
                noteCell.setCellValue(propertyParkingGetVO.getCreateTime());

            }
            String fileName = String.format("%s_ParkingInfo_%s.xls",
                    propertyParkingGetListDTO.getProjectId(),
                    DateFormatUtils.format(new Date(), "yyyyMMddHHmmssSSS"));
            fileName = URLEncoder.encode(fileName, "UTF-8");
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            workbook.write(os);
            byte[] content = os.toByteArray();
            InputStream exportFileStream = new ByteArrayInputStream(content);
            String exportFileUrl = uploadFile(exportFileStream,fileName);
            if (StringUtils.isBlank(exportFileUrl)){
                return new MessageVO(PropertyErrorCodeEnum.PROJECT_EXPORT_FILE_SAVE_ERR.getErrorCode());
            }
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), (Object) exportFileUrl);
        } catch (Exception e) {
            throw new DataAccessException("【物业-物业管理】导出车位表单失败",e);
        }
    }

    /**
     * <desc>
     *      导入车位表单
     * </desc>
     *
     * @return 标准格式化响应结果
     * @author wangzhi
     * @createDate 2018/08/17
     */
    @ResponseBody
    @PostMapping("importParkings")
    @LoggerInfo(operateDesc = LogDescConstant.PARKING_EXPORT_LOG_DESC)
    @AuthAccessRequired
    public Object importParkings(BaseDTO baseDTO, HttpServletRequest httpServletRequest){
        try {
            baseDTO = HttpProtocolUtil.parseRequestParamToDTO(BaseDTO.class, httpServletRequest);
            if (baseDTO == null) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            if (StringUtils.isBlank(baseDTO.getProjectId())) {
                return new MessageVO(PropertyErrorCodeEnum.PUB_PROJECT_ID_EMPTY_ERR.getErrorCode());
            }
            boolean isMultipart = ServletFileUpload.isMultipartContent(httpServletRequest);
            if (!isMultipart) {
                //是否是带文件上传的表单
                return new MessageVO(PropertyErrorCodeEnum.PROJECT_IMPORT_FILE_LOST_ERR.getErrorCode());
            }
            MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) httpServletRequest;
            Map<String, MultipartFile> fileList = multipartRequest.getFileMap();
            if (fileList.size() < 1) {
                return new MessageVO(PropertyErrorCodeEnum.PROJECT_IMPORT_FILE_LOST_ERR.getErrorCode());
            }
            if (fileList.size() > 1) {
                //目前仅支持一次处理单个文件
                return new MessageVO(PropertyErrorCodeEnum.PROJECT_EXCEL_FILE_TOO_MANY_ERR.getErrorCode());
            }
            List<HSSFSheet> availableSheets = new ArrayList<>(); //合法的Sheet页
            //获取Excel文件
            Map.Entry<String, MultipartFile> fileEntry = fileList.entrySet().iterator().next();
            MultipartFile excelFile = fileEntry.getValue();
            String excelFileName = excelFile.getOriginalFilename();
            // 获取上传文件的类型
            String excelContentType = StringHandlerUtil.copySubStr(excelFileName, excelFileName.lastIndexOf('.'), excelFileName.length());
            if (!(".xls".equalsIgnoreCase(excelContentType) || ".xlsx".equalsIgnoreCase(excelContentType))) {
                return new MessageVO(PropertyErrorCodeEnum.PROJECT_IMPORT_FILE_TYPE_ERR.getErrorCode());
            }
            List<PropertyParkingRowDTO> errorImportDataList;
            List<PropertyParkingSaveDTO> propertyParkingSaveDTOList;
            //创建Excel操作对象，07之前版本(*.xls)使用HSSFWorkBook 07之后版本使用（*.xlsx）XSSFWorkbook
            POIFSFileSystem fileSystem = new POIFSFileSystem(excelFile.getInputStream());
            try {
                try (HSSFWorkbook workbook = new HSSFWorkbook(fileSystem)) {

                    //对导入文件的数据格式等基本信息进行合法性初步检测
                    MessageVO messageVO = this.checkImportFileValid(workbook, availableSheets);
                    if (!messageVO.getMsgCode().equals(BaseErrorCodeEnum.SUCCESS.getErrorCode().getMainCode())) {
                        return messageVO;
                    }
                    //处理Excel文件中的车位数据
                    propertyParkingSaveDTOList = new ArrayList<>();
                    errorImportDataList = this.getImportParkingsFromFile(propertyParkingSaveDTOList, availableSheets,baseDTO.getProjectId());
                }
            } finally {
                fileSystem.close();
            }

            if (errorImportDataList == null) {
                return new MessageVO(PropertyErrorCodeEnum.IMPORT_DATA_TOO_MANY_ERR.getErrorCode());
            }
            //若有非法数据，返回非法数据
            if (!errorImportDataList.isEmpty()) {
                return new MessageVO(PropertyErrorCodeEnum.IMPORT_FILE_INFO_INVALID_ERR.getErrorCode(), errorImportDataList);
            }

            iPropertyParkingServiceClient.batchSaveParkings(baseDTO.getProjectId(),propertyParkingSaveDTOList);

            // 等待1秒再返回前端，一定程度上缓解前端导入成功后马上查询时尚无数据的情况
            Thread.sleep(1000);
            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
        } catch (Exception e) {
            throw new DataAccessException("【物业-物业管理】导入车位表单失败",e);
        }
    }

    /**
     * <desc>
     *      从可用的Sheet页中解析车位信息
     * </desc>
     *
     * @param propertyParkingSaveDTOList 从Excel(*.xls)导入地址信息数据传输对象(车位信息,用于保存到数据库)
     * @param availableSheets 合法可用到Sheet页
     * @return 错误的车位信息及其错误原因
     * @author wangzhi
     * @createDate 2018/08/17
     */
    private List<PropertyParkingRowDTO> getImportParkingsFromFile(List<PropertyParkingSaveDTO> propertyParkingSaveDTOList, List<HSSFSheet> availableSheets ,String projectId) throws Exception {
        // Excel单元格数据操作对象
        DataFormatter dataFormatter = new DataFormatter();
        // 错误的行信息列表
        List<PropertyParkingRowDTO> errorImportDataList = new ArrayList<>();
        int totalRowsCount = 0;
        List<String> parkingNumList = new ArrayList<>();
        //遍历所有可用Sheet，逐行处理每个Sheet的数据
        for (HSSFSheet oneSheet : availableSheets) {
            int rowsCountOfCurrentSheet = oneSheet.getPhysicalNumberOfRows();
            totalRowsCount += rowsCountOfCurrentSheet;
            if (totalRowsCount > PlatformConstants.MAX_IMPORT_ADDRESS_COUNT + 1) {
                return null;
            }
            for (int rowIndex = 1; rowIndex < rowsCountOfCurrentSheet; rowIndex++) {
                HSSFRow row = oneSheet.getRow(rowIndex);
                //对当前Sheet中的当前行进行数据处理
                PropertyParkingRowDTO propertyParkingRowDTO = handleOneRowAddressInfo(row,propertyParkingSaveDTOList, dataFormatter,projectId,parkingNumList);
                //若存在错误信息，则将加入错误列表
                if (!propertyParkingRowDTO.getErrorCodes().isEmpty()) {
                    this.addErrorParkingInfoToList(errorImportDataList,propertyParkingRowDTO);
                }
            }
        }
        return errorImportDataList;
    }

    /**
     * <desc>
     *      根据Excel的一行数据获取单条"车位信息及其错误码列表".
     * </desc>
     *
     * @param hssfRow Excel的一行数据
     * @param propertyParkingSaveDTOList 从Excel(*.xls)导入地址信息数据传输对象(车位信息,用于保存到数据库)
     * @param dataFormatter Excel单元格数据的读取器
     * @return 错误码列表
     * @author wangzhi
     * @createDate 2018/08/17
     */
    private PropertyParkingRowDTO handleOneRowAddressInfo(HSSFRow hssfRow, List<PropertyParkingSaveDTO> propertyParkingSaveDTOList, DataFormatter dataFormatter,String projectId,List<String> parkingNumList) throws Exception {
        PropertyParkingRowDTO propertyParkingRowDTO = new PropertyParkingRowDTO();
        PropertyParkingSaveDTO propertyParkingSaveDTO = new PropertyParkingSaveDTO();
        List<ErrorCode> errorCodes = propertyParkingRowDTO.getErrorCodes();
        //首先登记所属的Sheet名称和行号
        propertyParkingRowDTO.setSheetName(hssfRow.getSheet().getSheetName());
        propertyParkingRowDTO.setRowNum(hssfRow.getRowNum() + 1);
        // 处理车位号
        String parkingNum = dataFormatter.formatCellValue(hssfRow.getCell(0));
        if (StringUtils.isBlank(parkingNum)) {
            errorCodes.add(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
        } else {
            parkingNum = parkingNum.trim();
            if (parkingNumList.contains(parkingNum)) {
                errorCodes.add(PropertyErrorCodeEnum.IMPORT_PARKING_EXIST_EXCEL_ERR.getErrorCode());
            }
            parkingNumList.add(parkingNum);
            String regex = "^[^\u4e00-\u9fa5]+$";
            if (!Pattern.compile(regex).matcher(parkingNum).matches()) {
                errorCodes.add(PropertyErrorCodeEnum.PARKING_NUM_CHINESE_ERR.getErrorCode());
            } else if (parkingNum.length() > 10) {
                errorCodes.add(PropertyErrorCodeEnum.PARKING_NUM_LONG_ERR.getErrorCode());
            } else {
                PropertyParkingGetOneDTO propertyParkingGetOneDTO = new PropertyParkingGetOneDTO();
                propertyParkingGetOneDTO.setParkingNum(parkingNum);
                propertyParkingGetOneDTO.setProjectId(projectId);
                PropertyParkingGetVO oneParking = iPropertyParkingServiceClient.getOneParking(propertyParkingGetOneDTO);
                if (oneParking != null) {
                    errorCodes.add(PropertyErrorCodeEnum.PARKING_NUM_EXIST_ERR.getErrorCode());
                } else {
                    propertyParkingSaveDTO.setParkingNum(parkingNum);
                }
            }
        }
        propertyParkingRowDTO.setParkingNum(parkingNum);

        // 处理车位面积
        String parkingArea = dataFormatter.formatCellValue(hssfRow.getCell(1));
        if (StringUtils.isBlank(parkingArea)) {
            errorCodes.add(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
        } else {
            parkingArea = parkingArea.trim();
            String regex = "^([1-9][0-9]{0,2}|0)(\\.\\d{1,2})?$";
            if (!Pattern.compile(regex).matcher(parkingArea).matches() || "0".equals(parkingArea)) {
                errorCodes.add(PropertyErrorCodeEnum.PARKING_AREA_ERR.getErrorCode());
            } else {
                propertyParkingSaveDTO.setParkingArea(parkingArea);
            }
        }
        propertyParkingRowDTO.setParkingArea(parkingArea);

        // 处理车位类型
        String parkingType = dataFormatter.formatCellValue(hssfRow.getCell(2));
        if (StringUtils.isBlank(parkingType)) {
            errorCodes.add(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
        } else {
            parkingType = parkingType.trim();
            int i = StringHandlerUtil.strToIntDef(parkingType, -1);
            if (NumberHandlerUtil.isInRange(i, 1, 3)) {
                propertyParkingSaveDTO.setParkingType(i);
            } else {
                errorCodes.add(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
        }
        propertyParkingRowDTO.setParkingType(parkingType);

        // 处理车位状态
        String parkingStatus = dataFormatter.formatCellValue(hssfRow.getCell(3));
        if (StringUtils.isBlank(parkingStatus)) {
            errorCodes.add(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
        } else {
            parkingStatus = parkingStatus.trim();
            int i = StringHandlerUtil.strToIntDef(parkingStatus, -1);
            if (NumberHandlerUtil.isInRange(i, 1, 7)) {
                propertyParkingSaveDTO.setParkingStatus(i);
            } else {
                errorCodes.add(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
        }
        propertyParkingRowDTO.setParkingStatus(parkingStatus);

        // 处理备注
        String remark = dataFormatter.formatCellValue(hssfRow.getCell(4));
        if (StringUtils.isNotBlank(remark)) {
            remark = remark.trim();
            if (remark.length() <= 50) {
                propertyParkingSaveDTO.setRemark(remark);
            } else {
                errorCodes.add(PropertyErrorCodeEnum.REMARK_LONG_ERR.getErrorCode());
            }
        }
        propertyParkingRowDTO.setRemark(remark);
        propertyParkingSaveDTOList.add(propertyParkingSaveDTO);
        return propertyParkingRowDTO;
    }

    /**
     * <desc>
     *     向错误列表中增加有错误的车位信息.
     * </desc>
     *
     * @param  errorImportDataList 错误列表
     * @param  propertyParkingRowDTO 有错误的车位信息
     * @author wangzhi
     * @createDate 2018/08/17
     */
    private void addErrorParkingInfoToList(List<PropertyParkingRowDTO> errorImportDataList, PropertyParkingRowDTO propertyParkingRowDTO) {
        for (PropertyParkingRowDTO oneAddressInfo:errorImportDataList){
            if ((oneAddressInfo.getRowNum() ==  propertyParkingRowDTO.getRowNum())
                    && (StringHandlerUtil.compareStrWithOutEmpty(oneAddressInfo.getSheetName(),propertyParkingRowDTO.getSheetName()))){
                return;
            }
        }
        errorImportDataList.add(propertyParkingRowDTO);
    }

    /**
     * <desc>
     *      对导入文件的文件格式等基本信息进行合法性初步检测
     * </desc>
     *
     * @param workbook Excel操作对象
     * @param availableSheets 合法可用到Sheet页
     * @return MessageVO 标准格式化响应结果
     * @author wangzhi
     * @createDate 2018/08/17
     */
    private MessageVO checkImportFileValid(HSSFWorkbook workbook, List<HSSFSheet> availableSheets) {
        //获取Excel的Sheet页面数，每个Excel文件至少会有一个Sheet页(Excel文件本身到限定)
        int sheetCount = workbook.getNumberOfSheets();
//        int totalRowsCount = 0;
        //遍历当前文件的所有Sheet页，进行合法性检测
        for (int sheetIndex = 0; sheetIndex < sheetCount; sheetIndex++) {
            HSSFSheet oneSheet = workbook.getSheetAt(sheetIndex);
            int rowsCountOfCurrentSheet = oneSheet.getPhysicalNumberOfRows();
//            totalRowsCount += rowsCountOfCurrentSheet;
            if (rowsCountOfCurrentSheet < 1) {
                continue;
            }
            //对当前Sheet的列数量进行合法性判断
            HSSFRow headerRow = oneSheet.getRow(0);
            int columnCount = oneSheet.getRow(0).getPhysicalNumberOfCells();
            if (columnCount != PlatformConstants.PARKING_EXCEL_COLUMN_TITLES.length) {
                return new MessageVO(PropertyErrorCodeEnum.PARKING_EXCEL_COLUMN_COUNT_MISMATCH_ERR.getErrorCode());
            }
            //每个Sheet页的第一页为列标题，进行标题头名称进行合法性判断
            DataFormatter dataFormatter = new DataFormatter();
            for (int columnIndex = 0; columnIndex < columnCount; columnIndex++) {
                String oneFieldValue = dataFormatter.formatCellValue(headerRow.getCell(columnIndex));

                String columnTitle = PlatformConstants.PARKING_EXCEL_COLUMN_TITLES[columnIndex];
                if (!StringHandlerUtil.compareStrWithOutEmpty(oneFieldValue, columnTitle)) {
                    ErrorCode errorCode = PropertyErrorCodeEnum.PARKING_EXCEL_COLUMN_TITLE_MISMATCH_ERR.getErrorCode();
                    return new MessageVO(errorCode,
                            String.format(errorCode.getCodeMsg(), oneFieldValue, columnTitle));
                }
            }
            //至少有一行实际数据可导入才加入Sheet处理列表
            if (rowsCountOfCurrentSheet > 1) {
                availableSheets.add(oneSheet);
            }
        }
        //没有数据
        if (availableSheets.isEmpty()) {
            return new MessageVO(PropertyErrorCodeEnum.PROJECT_IMPORT_FILE_NO_DATA_ERR.getErrorCode());
        }
        return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode());
    }

    /**
     * <desc>
     *      Ftp上传文件，返回Url.
     * </desc>
     *
     * @param inputStream 文件流
     * @param fileName 文件名称
     * @return 文件上传成功后会返回Url,否则返回空
     * @author wangzhi
     * @createDate 2018/08/17
     */
    private String uploadFile(InputStream inputStream, String fileName) throws IOException {
        String fileUrl = "";
        String fileType = StringHandlerUtil.copySubStr(fileName, fileName.lastIndexOf('.') + 1, fileName.length());
        UploadFileUtil.UploadFile uploadFileUtil = new UploadFileUtil().new UploadFile(
                FILE_FTP_HOST,
                FILE_FTP_USERNAME,
                FILE_FTP_PASSWORD,
                FILE_FTP_PORT,
                inputStream,
                fileType,
                FILE_ACCESS_URL,
                FileCatalogEnum.PROPERTY_PARKING_AND_CAR_FILE.getType()
        );
        Map<String, Object> resultMap = UploadFileUtil.uploadFile(uploadFileUtil);
        Boolean returnCode = (Boolean)resultMap.get("returnCode");
        if (returnCode == false){
            return fileUrl;
        }
        fileUrl = resultMap.get("accessPath").toString();
        return fileUrl;
    }

}
